﻿using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;

namespace Nirvana
{
   [CustomEditor(typeof(UIVariableTable))]
    public sealed class UIVariableTableEditor : Editor
    {
        private SerializedProperty variablesProp;
        private ReorderableList reorderableList;
        private Dictionary<int, SerializedProperty> variablesMap = new Dictionary<int, SerializedProperty>();
        private HashSet<int> variableIndexHash = new HashSet<int>();
        private Dictionary<string, int> variableNameMap = new Dictionary<string, int>();

        public override void OnInspectorGUI()
        {
            serializedObject.Update();
            reorderableList.DoLayoutList();
            if (serializedObject.ApplyModifiedProperties())
            {
                variablesMap.Clear();
                ReLoad();
            }
            UIVariableTable table = (UIVariableTable)this.target;
            if (GUILayout.Button("Sort", new GUILayoutOption[0]))
            {
                Undo.RecordObject(table, "Sort Variable Table");
                base.serializedObject.Update();
                table.Sort();
                base.serializedObject.ApplyModifiedProperties();
            }
        }

        void OnEnable()
        {
            if (this.target == null) return;
            variablesProp = serializedObject.FindProperty("variables");
            reorderableList = new ReorderableList(serializedObject, variablesProp);
            reorderableList.drawElementCallback = DrawNameElement;//绘制每个元素的回调
            reorderableList.drawHeaderCallback = DrawHeader;//绘制列表表头
            reorderableList.onAddCallback = OnAddCallback;//添加按键事件回调
            reorderableList.elementHeightCallback = OnElementHeightCallback;
            ReLoad();
        }

        private void DrawHeader(Rect rect)
        {
            GUI.Label(rect, "Variables:");
        }
        private void DrawNameElement(Rect rect,int index, bool isActive, bool isFocused)
        {
            SerializedProperty prop;
            if (!this.variablesMap.TryGetValue(index, out prop))
            {
                prop = this.variablesProp.GetArrayElementAtIndex(index);
                this.variablesMap.Add(index, prop);
            }

            bool flag = this.variableIndexHash.Contains(index);
            Color color = GUI.color;
            if (flag) GUI.color = new Color(1f, 0.5f, 0.5f, 1);
            var variablename = prop.FindPropertyRelative("variableName");
            var variabletype = prop.FindPropertyRelative("variableType");
            Rect r0 = new Rect(rect.x + 8f, rect.y, 16f, EditorGUIUtility.singleLineHeight);
            Rect r1 = new Rect(rect.x + 12f, rect.y, (rect.width - 12f) / 2f - 5f, EditorGUIUtility.singleLineHeight);
            Rect r2 = new Rect(rect.x + rect.width / 2f + 5f, rect.y, (rect.width - 12f) / 2f - 5f, EditorGUIUtility.singleLineHeight);
            prop.isExpanded = EditorGUI.Foldout(r0, prop.isExpanded, GUIContent.none);//三角按键
            EditorGUI.PropertyField(r1, variablename, GUIContent.none);
            EditorGUI.PropertyField(r2, variabletype, GUIContent.none);
            Rect r3 = new Rect(rect.x + 12f, rect.y + EditorGUIUtility.singleLineHeight, rect.width - 12f, EditorGUIUtility.singleLineHeight);
            switch ((UIVariableType)variabletype.enumValueIndex)
            {
                case UIVariableType.Boolean:
                    {
                        var attprop = prop.FindPropertyRelative("boolValue");
                        attprop.boolValue = EditorGUI.ToggleLeft(r3, GUIContent.none, attprop.boolValue);
                        break;
                    }
                case UIVariableType.Integer:
                    {
                        var attprop = prop.FindPropertyRelative("intValue");
                        attprop.intValue = EditorGUI.IntField(r3, GUIContent.none, attprop.intValue);
                        break;
                    }
                case UIVariableType.Float:
                    {
                        var attprop = prop.FindPropertyRelative("floatValue");
                        attprop.floatValue = EditorGUI.FloatField(r3, GUIContent.none, attprop.floatValue);
                        break;
                    }
                case UIVariableType.String:
                    {
                        var attprop = prop.FindPropertyRelative("stringValue");
                        attprop.stringValue = EditorGUI.TextField(r3, GUIContent.none, attprop.stringValue);
                        break;
                    }
                case UIVariableType.Asset:
                    {
                        var attprop = prop.FindPropertyRelative("assetValue");
                        DrawAssetID(r3, attprop);
                        break;
                    }
            }

            if (prop.isExpanded)
            {
                UIVariableTable table = (UIVariableTable)this.target;
                UIVariable variable = table.GetVariable(index);
                if (variable.UIVariableBindList.Count > 0)
                {
                    GUI.enabled = false;
                    Rect r4 = new Rect(rect.x + 12f, rect.y + EditorGUIUtility.singleLineHeight, rect.width - 12f, EditorGUIUtility.singleLineHeight);
                    foreach(var p in variable.UIVariableBindList)
                    {
                        r4.y += EditorGUIUtility.singleLineHeight;
                        if (p != null)
                        {
                            EditorGUI.ObjectField(r4, p, p.GetType(), true);
                        }
                        else
                        {
                            EditorGUI.ObjectField(r4, null, typeof(UnityEngine.Object), true);
                        }
                    }
                    GUI.enabled = true;
                }
            }
            GUI.color = color;
        }

        private void DrawAssetID(Rect rect,SerializedProperty prop)
        {
            var bundleNameprop = prop.FindPropertyRelative("bundlename");
            var assetNameprop = prop.FindPropertyRelative("assetname");
            Rect r0 = new Rect(rect.x, rect.y, rect.width / 2f, rect.height);
            Rect r1 = new Rect(rect.x + rect.width / 2f, rect.y, rect.width / 2f, rect.height);
            EditorGUI.BeginChangeCheck();
            bundleNameprop.stringValue = EditorGUI.TextField(r0, GUIContent.none, bundleNameprop.stringValue);
            assetNameprop.stringValue = EditorGUI.TextField(r1, GUIContent.none, assetNameprop.stringValue);
            if (EditorGUI.EndChangeCheck())
            {
                string _bundlename = bundleNameprop.stringValue;
                string _assetname = assetNameprop.stringValue;
                if (!string.IsNullOrEmpty(_bundlename) && !string.IsNullOrEmpty(_assetname))
                {
                    string[] assetPaths = AssetDatabase.GetAssetPathsFromAssetBundleAndAssetName(_bundlename, Path.GetFileNameWithoutExtension(_assetname));
                    string path = null;
                    if (Path.HasExtension(_assetname))
                    {
                        string extension = Path.GetExtension(_assetname);
                        foreach (string t in assetPaths)
                        {
                            if (Path.GetExtension(t) == extension)
                            {
                                path = t;
                                break;
                            }
                        }
                    }
                    else if (assetPaths.Length > 0)
                    {
                        path = assetPaths[0];
                    }
                    if (path != null)
                    {
                        SerializedProperty guuid = prop.FindPropertyRelative("assetguiid");
                        guuid.stringValue = AssetDatabase.AssetPathToGUID(path);
                    }
                }

            }



        }


        private void OnAddCallback(ReorderableList _list)
        {
            UIVariableTable table = (UIVariableTable)this.target;
            table.InitDefaultVariable();
            EditorUtility.SetDirty(this.target);
        }

        private float OnElementHeightCallback( int index)
        {
            SerializedProperty prop;
            if (!this.variablesMap.TryGetValue(index,out prop))
            {
                prop = this.variablesProp.GetArrayElementAtIndex(index);
                this.variablesMap.Add(index, prop);
            }
            
            if (!prop.isExpanded)//此元素是否展开
            {
                return 2f * EditorGUIUtility.singleLineHeight;
            }
            UIVariableTable table = (UIVariableTable)this.target;
            UIVariable variable = table.GetVariable(index);
            return (float)(2 + variable.UIVariableBindList.Count) * EditorGUIUtility.singleLineHeight;
        }

        private void ReLoad()
        {
            variableIndexHash.Clear();
            variableNameMap.Clear();
            for(int i = 0; i < this.variablesProp.arraySize; i++)
            {
                var element = this.variablesProp.GetArrayElementAtIndex(i);
                var variablename = element.FindPropertyRelative("variableName");
                if (this.variableNameMap.ContainsKey(variablename.stringValue))
                {
                    this.variableIndexHash.Add(this.variableNameMap[variablename.stringValue]);
                    this.variableIndexHash.Add(i);
                }
                else
                {
                    this.variableNameMap.Add(variablename.stringValue,i);  
                }
            }
        }

    }
}

